package com.lili.config;

import com.lili.filter.JWTFilter;
import com.lili.service.MyShiroRealm;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import javax.servlet.Filter;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;


/**
 * Shiro配置
 *
 * @author huangfan
 * @date 2016年9月28日
 */
@Configuration
public class ShiroConfig {

    private static Map<String, String> filterChainDefinitionMap = Collections.synchronizedMap(new LinkedHashMap<String, String>());

    @Bean
    public MyShiroRealm myShiroRealm() {
        MyShiroRealm myShiroRealm = new MyShiroRealm();
//        myShiroRealm.setCredentialsMatcher(credentialsMatcher());
        // myShiroRealm.setCachingEnabled(true);
        // myShiroRealm.setAuthenticationCachingEnabled(true);
        // myShiroRealm.setAuthenticationCacheName("authenticationCache");
        // myShiroRealm.setAuthorizationCachingEnabled(false);
        myShiroRealm.setName("myShiroRealmName");
        myShiroRealm.setAuthorizationCacheName("authorizationCache");
        return myShiroRealm;
    }

    @Bean
    public CredentialsMatcher credentialsMatcher() {
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("md5");
        hashedCredentialsMatcher.setHashIterations(1);
        hashedCredentialsMatcher.setStoredCredentialsHexEncoded(true);
        return hashedCredentialsMatcher;
    }


//	@Bean
//	public DefaultWebSessionManager sessionManager() throws Exception {
//		DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
//		sessionManager.setGlobalSessionTimeout(1800000);// 1800000
//		sessionManager.setSessionValidationInterval(1800000);
//		// sessionManager.setDeleteInvalidSessions(true);
//		// sessionManager.setSessionValidationSchedulerEnabled(true);
//		// sessionManager.setSessionValidationScheduler(sessionValidationScheduler());
//		// sessionManager.setSessionDAO(redisSessionDao());
//		sessionManager.setSessionIdCookieEnabled(true);
//		return sessionManager;
//	}

    @Bean
    public DefaultWebSecurityManager defaultWebSecurityManager() throws Exception {
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        defaultWebSecurityManager.setRealm(myShiroRealm());
//		dwsm.setSessionManager(sessionManager());
        // 采用redis缓存
//		dwsm.setCacheManager(getRedisCacheManager());
        // dwsm.setCacheManager(getEhCacheManager());

        DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
        DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
        defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
        subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
        defaultWebSecurityManager.setSubjectDAO(subjectDAO);
        return defaultWebSecurityManager;
    }

    /**
     * 下面的代码是添加注解支持
     */
    @Bean
    @DependsOn("lifecycleBeanPostProcessor")
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        // 强制使用cglib，防止重复代理和可能引起代理出错的问题
        // https://zhuanlan.zhihu.com/p/29161098
        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
        return defaultAdvisorAutoProxyCreator;
    }

    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }


    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() throws Exception {
        AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
        aasa.setSecurityManager(defaultWebSecurityManager());
        return aasa;
    }

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(Constant constant) throws Exception {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager());

        filterChainDefinitionMap.put("/manager/overTime", "anon");
        filterChainDefinitionMap.put("/manager/tokenIsNull", "anon");
        filterChainDefinitionMap.put("/manager/tokenValidate", "anon");
        filterChainDefinitionMap.put("/manager/login", "anon");
//        filterChainDefinitionMap.put("/perm/selectXasUser", "anon");
//        filterChainDefinitionMap.put("/perm/addXasUser", "anon");
//        filterChainDefinitionMap.put("/perm/updateXasUser", "anon");
//        filterChainDefinitionMap.put("/perm/delXasUser", "anon");
//        filterChainDefinitionMap.put("/perm/selectXasRole", "anon");
//        filterChainDefinitionMap.put("/perm/selectAllXasRole", "anon");
//        filterChainDefinitionMap.put("/perm/addXasRole", "anon");
//        filterChainDefinitionMap.put("/perm/updateXasRole", "anon");
//        filterChainDefinitionMap.put("/perm/delXasRole", "anon");
//        filterChainDefinitionMap.put("/perm/xasPermissionList", "anon");
//        filterChainDefinitionMap.put("/perm/selectXasRoleById", "anon");
//
//        filterChainDefinitionMap.put("/userInfo/userInfoListPage", "anon");
//        filterChainDefinitionMap.put("/userInfo/xasUserAddressList", "anon");
//        filterChainDefinitionMap.put("/userInfo/xasUserCoinRecordsListByPhone", "anon");
//        filterChainDefinitionMap.put("/userInfo/xasUserBankcardListByPhone", "anon");
//        filterChainDefinitionMap.put("/userInfo/xasUserPointRecordsListByPhone", "anon");
//        filterChainDefinitionMap.put("/userInfo/xasUserBalanceRecordsListByPhone", "anon");
//        filterChainDefinitionMap.put("/userInfo/xasUserBenefitsRecordsListByPhone", "anon");
//        filterChainDefinitionMap.put("/userInfo/xasUserAuthenticationRecords", "anon");
//        filterChainDefinitionMap.put("/coupon/xasUserCouponRecords", "anon");
//        filterChainDefinitionMap.put("/goods/upFilePic", "anon");
//        filterChainDefinitionMap.put("/goods/secGoodsCategory", "anon");
//        filterChainDefinitionMap.put("/goods/thrGoodsCategory", "anon");
//        filterChainDefinitionMap.put("/goods/selectGoodsCategory", "anon");
//        filterChainDefinitionMap.put("/goods/addGoodsCategory", "anon");
//        filterChainDefinitionMap.put("/goods/updateGoodsCategory", "anon");
//        filterChainDefinitionMap.put("/goods/delGoodsCategory", "anon");
//
//
//        filterChainDefinitionMap.put("/goods/selectXasGoodsList", "anon");
//        filterChainDefinitionMap.put("/goods/addXasGoodsList", "anon");
//        filterChainDefinitionMap.put("/goods/updateXasGoodsList", "anon");
//        filterChainDefinitionMap.put("/goods/delXasGoodsList", "anon");
//
//
//
//        filterChainDefinitionMap.put("/goods/selectXasGoodsPropConfig", "anon");
//        filterChainDefinitionMap.put("/goods/selectXasHotSalesGoods", "anon");
//        filterChainDefinitionMap.put("/goods/selectXasLimitedGoods", "anon");
//        filterChainDefinitionMap.put("/goods/selectXasNewGoods", "anon");
//        filterChainDefinitionMap.put("/config/login1", "anon");
        filterChainDefinitionMap.put(constant.getTokenIsNull(), "anon");
        filterChainDefinitionMap.put(constant.getOverTime(), "anon");
        filterChainDefinitionMap.put(constant.getTokenValidate(), "perms['']");
        Map<String, Filter> filterMap = new HashMap<>();
        filterMap.put("jwt", new JWTFilter(constant));
        shiroFilterFactoryBean.setFilters(filterMap);


        // List<Permission> permList = null;
        // for (Permission perm : permList) {
        // filterChainDefinitionMap.put(perm.getUrl(), perm.getPerms());
        // }
//		List<Permission> list = null;
        // if (list != null && list.size() > 0) {
        // for (Permission p : list) {
        // filterChainDefinitionMap.put(p.getUrl(), p.getPerms());
        // }
        // }
        filterChainDefinitionMap.put("/**", "jwt");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

}
